package java代理模式.java动态代理;



/**
 * @author coderFu
 * @create 2022/2/15
 * 动态代理测试类
 *
 * 代理模式：当一个对象不能直接使用，可以在客户端和目标对象直接创建一个中介，这个中介就是代理。
 * 作用：控制访问，在代理中，控制是否可以调用目标对象的方法
 *       功能增强：我们可以在完成目标对象调用时，额外一些功能.
 * 代理的实现方式：1、静态代理：代理类是手工实现的java文件，我们代理关系已经确定好了。
 *                           优点：容易理解，使用方便。
 *                           缺点：在目标类比较多的时候，会产生大量的代理类，当接口改变时，影响的代理类和目标类
 *                 2、动态代理：使用反射机制，在程序执行中，创建代理对象。特点：不用创建类文件，代理类是活动的，可设置的。
 *                          jdk动态创建字节码文件。
 *
 *                          jdk动态代理：使用java反射包中的类和接口实现动态代理的功能
 *                          java.lang.reflect  InvocationHandler, Method, Proxy
 *                         cglib： cglib是第三方的工具库，创建代理对象
 *                         cglib的原理是继承，cglib通过继承目标类，创建它的子类，在子类
 *                         中重写父类中的同名方法，实现功能的修改。
 *                         因为cglib是继承，重写方法，所以要求目标类不能是final的，也不能是
 *                         final的。cglib的要求目标比较宽松，只要能继承就可以。
   *                               Spring  Aop
 *                         对于无接口的类，必须使用cglib动态代理
 *
 *                3、jdk中的动态代理
 *                      1、InvocationHandler 2、Method 3、 Proxy，newInstance（）
 *
 *                      2、InvocationHandler接口（调用处理器）中就一个方法 invoke();
 *                            invoke 表示代理对象要执行的方法。 代理类要完成的功能写在
 *                            invoke方法中。
 *
 *                            代理类完成的功能： 1、调用目标方法
 *                                               2、功能增强，在目标方法的执行前
 *                                               执行后要增强的功能。
 *
 *                             方法原型：
 *                               参数：object proxy：jdk创建的代理对象，无需赋值
 *                                     Method method:目标类中的方法
 *                                     args： 目标类中的方法参数
 *                   public object invoke(Object proxy, Method method, Object[] args)
 *                   创建一个类实现这个接口：
 *                              重写invoke（）方法，把原来静态代理中代理了要完成的功能，写在里面
 *                    invocationHandler 接口，表示你的代理要干什么。
 *
 *
 *                    method: 表示方法的，确切的说就是目标类中的方法
 *                           作用：通过这个目标类Method，可以执行对应的目标类方法
 *                           反射执行： Method.invoke（目标方法对象，方法的参数）；
 *                   声明： method.invoke()就是来执行目标方法的，等同于静态代理中
 *                        factory.sell();
 *
 *                   Proxy类： 核心的对象： 创建代理对象。 之前创建对象都是 new
 *                   现在我们是使用Proxy类的方法，代替new 创建使用
 *
 *                   方法： 静态方法： newProxyInstance（）
 *                   作用是： 创建代理对象： 等同于 new staticProxy
 *
 *                   方法原型：
 *                   public static Object newProxyInstance(ClassLoader loader,
 *                                           Class<?>[] interfaces,
 *                                           InvocationHandler h)
 *                         参数： ClassLoader  类加载器： 向内存中加载对象的，使用反射获取
 *                          目标对象的类加载器。
 *
 *                          interfaces 接口  目标对象所实现的接口 ，反射获取
 *
 *                          InvocationHandler h ； 我们自己实现的对象 代理类要完成的功能
 *                     返回值就是代理对象：  ProxyObject： 得到代理对象
 *
 *
 *              实现动态代理的步骤：
 *
 *
 *
 */
public class DynamicProxyTest {
    public static void main(String[] args) {

        //获取被代理对象
        Subject subject = new CarSubject();

        DynamicProxy dynamicProxy = new DynamicProxy(subject);
        Subject dynamicProxy1 = dynamicProxy.getDynamicProxy();
        //获取代理对象， 执行方法
        //此处实际上执行的是： InvocationHandler中的 invoke方法
        String s = dynamicProxy1.addSubject();
        /**
         * 内部代码的实质， super.h.invoke(this,m3,(Object[]) null)
         *
         * asm: 操作字节码 生产代理类$proxy    字节码工具：javassist dubbo         */
        System.out.println(s);


    }
}
